const ChargeAccount = require('../entity/charge/chargeaccount');
const ChargePackage = require('../entity/charge/chargepackage');
const ChargeRecord = require('../entity/charge/chargerecord');
const Order = require('../entity/product/order');
const AdminUser = require('../entity/user/adminuser');
const TaskIncome = require('../entity/account/taskincome');
const ChargeConsumeRecord = require('../entity/charge/chargeconsumerecord');

const ChargeRecordStatus = require('../module/const/ChargeRecordStatus');
const OrderStatus = require('../module/const/OrderStatus');
const SourceType = require('../module/const/IncomeSource');

const userService = require('./user');
const { CommonServiceError } = require('../module/error/svcerror');
const { getCurrentTimestamp } = require('../module/tool/time');
const { generateRandomChargeOrderIdWithTime } = require('../module/tool/common');

const {
    requestPaymentOrder,
    queryPaymentOrder,
    addPaymentOrderStatusListener,
    balanceChargeSceneId
} = require('./payment-merchant');

let hasPaymentOrderStatusListener = false;
if (!hasPaymentOrderStatusListener) {
    hasPaymentOrderStatusListener = true;
    addPaymentOrderStatusListener(balanceChargeSceneId, async (paymentOrderId, paymentOrderStatus) => {
        const chargeRecordEntity = new ChargeRecord();
        const chargeRecordModel = chargeRecordEntity.getModel();

        const chargeRecordData = await chargeRecordModel.findOne({
            paymentOrderId: paymentOrderId
        });

        if (!chargeRecordData) {
            return;
        }
        if (paymentOrderStatus === '3' && chargeRecordData.status === ChargeRecordStatus.enumValue.WaitingPay) {
            // 支付成功
            chargeRecordData.status = ChargeRecordStatus.enumValue.Payed;
            chargeRecordData.payTime = getCurrentTimestamp();
            chargeRecordData.save();

            const chargeAccountEntity = new ChargeAccount();
            const chargeAccountModel = chargeAccountEntity.getModel();
            const chargeAccountData = await chargeAccountModel.findOne({ _id: chargeRecordData.accountId });
            // 账户加钱
            let totalAmount = chargeRecordData.fee;
            if (chargeRecordData.giftFee) {
                totalAmount = totalAmount + chargeRecordData.giftFee;
            }
            await chargeAccountModel.findByIdAndUpdate(chargeAccountData._id, { $inc: { totalAmount } });

            // 充值成功 加区域收入
            const AdminUserModel = new AdminUser().getModel();
            const adminInfo = await AdminUserModel.findOne({ areaId: chargeRecordData.areaId });
            if (!adminInfo) {
                throw new CommonServiceError('未查询到管理员');
            }

            const TaskIncomeEntity = new TaskIncome();
            const TaskIncomeModel = TaskIncomeEntity.getModel();
            if (!await TaskIncomeModel.exists({
                adminId: adminInfo._id,
                areaId: chargeRecordData.areaId,
                orderId: chargeRecordData._id
            })) {
                await TaskIncomeEntity.getDoc({
                    adminId: adminInfo._id,
                    areaId: chargeRecordData.areaId,
                    price: chargeRecordData.fee,
                    orderId: chargeRecordData._id,
                    source: SourceType.recharge.value
                }).save();
            }
        } else {
            if (chargeRecordData) {
                await chargeRecordModel.findByIdAndUpdate(chargeRecordData._id, { status: ChargeRecordStatus.enumValue.WaitingPay });
            }
        }
    }).then(() => {
        console.log('addPaymentOrderStatusListener success');
    });
}

async function submitCharge (userId, areaId, chargePackageId, fee, giftFee) {
    const userInfo = await userService.getUserInfo(userId);
    if (userInfo._id.toString() !== userId) {
        throw new CommonServiceError('充值对象有误');
    }
    if (userInfo.authAreaId.toString() !== areaId) {
        throw new CommonServiceError('充值地区有误');
    }
    const chargeAccountEntity = new ChargeAccount();
    const chargeAccountModel = chargeAccountEntity.getModel();
    if (!Number.isFinite(fee) || fee <= 0) {
        throw new CommonServiceError('输入金额不正确');
    }

    let accountId = '';
    if (!await chargeAccountModel.exists({
        userId,
        areaId
    })) {
        const chargeAccountData = await chargeAccountEntity.getDoc({
            userId,
            areaId
        }).save();
        accountId = chargeAccountData._id;
    } else {
        const chargeAccountData = await chargeAccountModel.findOne({
            userId,
            areaId
        });
        accountId = chargeAccountData._id;
    }

    let chargeRecordData = {};

    const chargeRecordEntity = new ChargeRecord();
    const chargeRecordModel = chargeRecordEntity.getModel();
    chargeRecordData = await chargeRecordEntity.getDoc({
        areaId,
        userId,
        status: ChargeRecordStatus.enumValue.WaitingPay,
        orderNo: generateRandomChargeOrderIdWithTime(),
        accountId
    }).save();
    if (chargePackageId) {
        const chargePackageModel = new ChargePackage().getModel();
        const chargePackageData = await chargePackageModel.findById(chargePackageId);

        if (!chargePackageData.isEnable) {
            throw new CommonServiceError('套餐已下架，请联系管理员');
        }
        if (chargePackageData.fee !== fee) {
            throw new CommonServiceError('充值套餐金额有误');
        }
        if (chargePackageData.giftFee !== giftFee) {
            throw new CommonServiceError('套餐赠送金额有误');
        }
        chargeRecordData.packageId = chargePackageId;
        chargeRecordData.fee = chargePackageData.fee;
        chargeRecordData.giftFee = chargePackageData.giftFee;
    } else {
        chargeRecordData.fee = fee;
    }
    await chargeRecordData.save();

    let returnData = {};
    if (chargeRecordData.status === ChargeRecordStatus.enumValue.WaitingPay) {
        if (chargeRecordData.fee > 0) {
            try {
                const {
                    paySign,
                    orderId
                } = await requestPaymentOrder(balanceChargeSceneId, userInfo.openid, Math.round(chargeRecordData.fee), '大力蛮牛充值下单');
                chargeRecordData.paymentOrderId = orderId;
                await chargeRecordData.save();
                returnData.paySign = paySign;
                returnData.chargeRecordId = chargeRecordData._id;
            } catch (e) {
                await chargeRecordModel.findByIdAndDelete(chargeRecordData._id);
                throw e;
            }
        }
    }

    return returnData;
}

// 废弃
async function orderRecordPaymentNotify (orderId) {
    const chargeRecordEntity = new ChargeRecord();
    const chargeRecordModel = chargeRecordEntity.getModel();
    const chargeRecordData = await chargeRecordModel.findById(ChargeRecord.toObjectId(orderId));

    const paymentOrderData = await queryPaymentOrder(chargeRecordData.paymentOrderId);

    if (paymentOrderData.status === '3' && chargeRecordData.status === ChargeRecordStatus.enumValue.WaitingPay) {
        // 支付成功
        chargeRecordData.status = ChargeRecordStatus.enumValue.Payed;
        chargeRecordData.payTime = getCurrentTimestamp();
        await chargeRecordData.save();

        const chargeAccountEntity = new ChargeAccount();
        const chargeAccountModel = chargeAccountEntity.getModel();
        const chargeAccountData = await chargeAccountModel.findOne({ _id: chargeRecordData.accountId });
        // 账户加钱
        let totalAmount = chargeRecordData.fee;
        if (chargeRecordData.giftFee) {
            totalAmount = totalAmount + chargeRecordData.giftFee;
        }
        await chargeAccountModel.findOneAndUpdate({ _id: chargeAccountData._id }, { $inc: { totalAmount } });
    } else {
        if (chargeRecordData) {
            await chargeRecordModel.findByIdAndUpdate(ChargeRecord.toObjectId(orderId), { status: ChargeRecordStatus.enumValue.WaitingPay });
        }

        const TaskIncomeEntity = new TaskIncome();
        const TaskIncomeModel = TaskIncomeEntity.getModel();
        const taskIncomeData = await TaskIncomeModel.findOne({ orderId: chargeRecordData._id });

        if (taskIncomeData) {
            await TaskIncomeModel.findByIdAndDelete(taskIncomeData._id);
        }
    }
    return 1;
}

// 扣余额并创建使用记录
async function createChargeConsumeRecord (orderId) {
    const orderEntity = new Order();
    const orderModel = orderEntity.getModel();
    const orderData = await orderModel.findById(orderId);
    const chargeConsumeRecordEntity = new ChargeConsumeRecord();
    await chargeConsumeRecordEntity.getDoc({
        userId: orderData.userId,
        areaId: orderData.areaId,
        orderId: orderData._id,
        price: orderData.price
    }).save();
    // 扣钱
    const chargeAccountEntity = new ChargeAccount();
    const chargeAccountModel = chargeAccountEntity.getModel();
    const chargeAccountData = await chargeAccountModel.findOne({
        userId: orderData.userId,
        areaId: orderData.areaId
    });

    if (chargeAccountData.totalAmount < orderData.price) {
        throw new CommonServiceError('账户余额不足');
    }

    await chargeAccountModel.updateOne({
        userId: orderData.userId,
        areaId: orderData.areaId
    }, { $inc: { totalAmount: -orderData.price } });

    return 1;
}

// 退还钱包余额
async function refundWalletBalance (orderId) {
    const orderEntity = new Order();
    const orderModel = orderEntity.getModel();
    const orderData = await orderModel.findById(orderId);
    if (!orderData) {
        throw new CommonServiceError('订单不存在');
    }
    const chargeAccountEntity = new ChargeAccount();
    const chargeAccountModel = chargeAccountEntity.getModel();
    const chargeAccountData = await chargeAccountModel.findOne({
        userId: orderData.userId,
        areaId: orderData.areaId
    });

    if (!chargeAccountData) {
        throw new CommonServiceError('账户不存在');
    }
    // 增加钱包余额
    await chargeAccountModel.updateOne({
        userId: orderData.userId,
        areaId: orderData.areaId
    }, { $inc: { totalAmount: orderData.price } });

    // 设置余额使用记录为取消
    const chargeConsumeRecordEntity = new ChargeConsumeRecord();
    const chargeConsumeRecordModel = chargeConsumeRecordEntity.getModel();
    await chargeConsumeRecordModel.findOneAndUpdate({
        userId: orderData.userId,
        areaId: orderData.areaId,
        orderId
    }, {
        status: OrderStatus.Cancel.value,
        cancelTime: getCurrentTimestamp()
    });
    return 1;
}

// 设置余额消费记录为已取消

module.exports = {
    submitCharge,
    orderRecordPaymentNotify,
    createChargeConsumeRecord,
    refundWalletBalance
};
